package cn.slipi.admin.biz;

import cn.slipi.admin.biz.vo.iface.CsmGrantVo;
import cn.slipi.admin.biz.vo.iface.GrantInfoVo;
import cn.slipi.admin.biz.vo.iface.PdrApiVo;
import cn.slipi.admin.common.dto.PageDTO;
import cn.slipi.admin.common.utils.dozer.impl.ConvertBean;
import cn.slipi.admin.controller.form.pdrapi.GrantListForm;
import cn.slipi.admin.controller.form.pdrapi.ListForm;
import cn.slipi.admin.controller.form.pdrapi.NoGrantListForm;
import cn.slipi.admin.controller.form.pdrapi.SaveForm;
import cn.slipi.admin.entity.CsmGrant;
import cn.slipi.admin.entity.CsmProject;
import cn.slipi.admin.entity.PdrApi;
import cn.slipi.admin.entity.PdrProject;
import cn.slipi.admin.service.PdrApiService;
import cn.slipi.admin.service.dto.in.pdrapi.GrantListDTO;
import cn.slipi.admin.service.dto.in.pdrapi.ListDTO;
import cn.slipi.admin.service.dto.in.pdrapi.NoGrantListDTO;
import cn.slipi.admin.service.dto.in.pdrapi.SaveDTO;
import cn.slipi.admin.service.dto.in.producer.HystrixParam;
import cn.slipi.admin.task.PublishTask;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class PdrApiBiz {

    @Autowired
    private PublishTask publishTask;

    @Autowired
    private ConvertBean convertBean;

    @Autowired
    private PdrApiService pdrApiService;

    /**
     * 熔断降级配置可调
     *
     * @param listForm
     * @return
     */
    public PageDTO<PdrApiVo> getList(ListForm listForm) {
        ListDTO listDTO = this.convertBean.convert(listForm, ListDTO.class);
        IPage<PdrApi> page = this.pdrApiService.getList(listDTO);
        List<PdrApi> pdrApiList = page.getRecords();
        List<PdrApiVo> producerVoList = new ArrayList<>();
        pdrApiList.forEach(pdrApi -> producerVoList.add(this.beanConvert(pdrApi)));
        return PageDTO.of(page, producerVoList);
    }

    public PageDTO<PdrApiVo> getNoGrantList(NoGrantListForm noGrantListForm) {
        NoGrantListDTO noGrantListDTO = this.convertBean.convert(noGrantListForm, NoGrantListDTO.class);
        IPage<PdrApi> page = this.pdrApiService.getNoGrantList(noGrantListDTO);
        List<PdrApi> pdrApiList = page.getRecords();
        List<PdrApiVo> producerVoList = new ArrayList<>();
        pdrApiList.forEach(pdrApi -> producerVoList.add(this.beanConvert(pdrApi)));
        return PageDTO.of(page, producerVoList);
    }

    public PageDTO<CsmGrantVo> getGrantList(GrantListForm grantListForm) {
        GrantListDTO grantListDTO = this.convertBean.convert(grantListForm, GrantListDTO.class);
        IPage<CsmGrant> page = this.pdrApiService.getGrantList(grantListDTO);
        List<CsmGrant> csmGrantList = page.getRecords();
        List<Integer> pdrApiIdList = csmGrantList.stream().map(CsmGrant::getPdrApiId).collect(Collectors.toList());
        Map<Integer, PdrApi> pdrApiMap = new HashMap<>();
        if (pdrApiIdList.size() > 0) {
            List<PdrApi> pdrApiList = this.pdrApiService.getListByIds(pdrApiIdList);
            pdrApiMap = pdrApiList.stream().collect(Collectors.toMap(PdrApi::getId, pdrApi -> pdrApi));
        }

        List<CsmGrantVo> csmGrantVoList = new ArrayList<>();
        Map<Integer, PdrApi> finalPdrApiMap = pdrApiMap;
        csmGrantList.forEach(csmGrant -> {
            CsmGrantVo csmGrantVo = this.convertBean.convert(csmGrant, CsmGrantVo.class);
            PdrApi pdrApi = finalPdrApiMap.getOrDefault(csmGrant.getPdrApiId(), null);
            if (pdrApi != null) {
                PdrApiVo pdrApiVo = this.beanConvert(pdrApi);
                csmGrantVo.setPdrApi(pdrApiVo);
            }
            csmGrantVoList.add(csmGrantVo);
        });

        return PageDTO.of(page, csmGrantVoList);
    }

    public PdrApiVo add(SaveForm saveForm) {
        SaveDTO saveDTO = this.convertBean.convert(saveForm, SaveDTO.class);
        PdrApi pdrApi = this.pdrApiService.add(saveDTO);
        return this.beanConvert(pdrApi);
    }

    public PdrApiVo update(Integer id, SaveForm saveForm) {
        SaveDTO saveDTO = this.convertBean.convert(saveForm, SaveDTO.class);
        PdrApi pdrApi = this.pdrApiService.update(id, saveDTO);
        return this.beanConvert(pdrApi);
    }

    public Boolean publish(Integer id) {
        List<Integer> ids = new ArrayList<>();
        ids.add(id);
        this.publishTask.publishApiBatch(ids);
        return true;
    }

    public List<GrantInfoVo> grantInfo(Integer id) {
        List<CsmProject> csmProjectList = this.pdrApiService.getCsmByPdrApiId(id);
        return this.convertBean.convert(csmProjectList, GrantInfoVo.class);
    }

    public Boolean publishBatch(List<Integer> apiIds) {
        this.publishTask.publishApiBatch(apiIds);
        return true;
    }

    private PdrApiVo beanConvert(PdrApi pdrApi) {
        PdrApiVo pdrApiVo = new PdrApiVo();
        pdrApiVo.setId(pdrApi.getId());
        pdrApiVo.setName(pdrApi.getName());
        pdrApiVo.setCode(pdrApi.getCode());
        pdrApiVo.setPath(pdrApi.getPath());
        pdrApiVo.setLoadIp(pdrApi.getLoadIp());
        pdrApiVo.setEnable(pdrApi.getEnable());
        pdrApiVo.setProtocol(pdrApi.getProtocol());
        pdrApiVo.setQueryType(pdrApi.getQueryType());
        pdrApiVo.setPdrProjectId(pdrApi.getPdrProjectId());
        pdrApiVo.setDescription(pdrApi.getDescription());
        pdrApiVo.setTranslateProtocol(pdrApi.getTranslateProtocol());
        pdrApiVo.setPermitsPerSecond(pdrApi.getPermitsPerSecond());
        pdrApiVo.setBlackList(pdrApi.getBlackList());
        pdrApiVo.setInParam(pdrApi.getInParam());
        pdrApiVo.setOutParam(pdrApi.getOutParam());
        pdrApiVo.setPublishTime(pdrApi.getPublishTime());
        pdrApiVo.setGlobalGrantParam(pdrApi.getGlobalGrantParam());
//        pdrApiVo.setHystrixParam(JSONObject.parseObject(pdrApi.getHystrixParam(), HystrixParam.class));
        pdrApiVo.setCreatedAt(pdrApi.getCreatedAt());
        pdrApiVo.setKeyUpdateTime(pdrApi.getKeyUpdateTime());
        return pdrApiVo;
    }

}
